﻿using System;

namespace BepInEx.Logging
{
    /// <summary>
    ///     The level, or severity of a log entry.
    /// </summary>
    [Flags]
    public enum LogLevel
    {
        /// <summary>
        ///     No level selected.
        /// </summary>
        None = 0,

        /// <summary>
        ///     A fatal error has occurred, which cannot be recovered from.
        /// </summary>
        Fatal = 1,

        /// <summary>
        ///     An error has occured, but can be recovered from.
        /// </summary>
        Error = 2,

        /// <summary>
        ///     A warning has been produced, but does not necessarily mean that something wrong has happened.
        /// </summary>
        Warning = 4,

        /// <summary>
        ///     An important message that should be displayed to the user.
        /// </summary>
        Message = 8,

        /// <summary>
        ///     A message of low importance.
        /// </summary>
        Info = 16,

        /// <summary>
        ///     A message that would likely only interest a developer.
        /// </summary>
        Debug = 32,

        /// <summary>
        ///     All log levels.
        /// </summary>
        All = Fatal | Error | Warning | Message | Info | Debug
    }

    /// <summary>
    ///     Helper methods for log level handling.
    /// </summary>
    public static class LogLevelExtensions
    {
        /// <summary>
        ///     Gets the highest log level when there could potentially be multiple levels provided.
        /// </summary>
        /// <param name="levels">The log level(s).</param>
        /// <returns>The highest log level supplied.</returns>
        public static LogLevel GetHighestLevel(this LogLevel levels)
        {
            var enums = Enum.GetValues(typeof(LogLevel));
            Array.Sort(enums);

            foreach (LogLevel e in enums)
                if ((levels & e) != LogLevel.None)
                    return e;

            return LogLevel.None;
        }

        /// <summary>
        ///     Returns a translation of a log level to it's associated console colour.
        /// </summary>
        /// <param name="level">The log level(s).</param>
        /// <returns>A console color associated with the highest log level supplied.</returns>
        public static ConsoleColor GetConsoleColor(this LogLevel level)
        {
            level = GetHighestLevel(level);
            return level switch
            {
                LogLevel.Fatal   => ConsoleColor.Red,
                LogLevel.Error   => ConsoleColor.DarkRed,
                LogLevel.Warning => ConsoleColor.Yellow,
                LogLevel.Message => ConsoleColor.White,
                LogLevel.Info    => ConsoleColor.DarkGray,
                LogLevel.Debug   => ConsoleColor.DarkGray,
                _                => ConsoleColor.Gray
            };
        }
    }
}
